home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / make-367.lha / make-3.67 / remote-cstms.c < prev    next >
C/C++ Source or Header  |  1993-02-04  |  8KB  |  272 lines

  1. /* This file implements an interface to the Customs daemon to do
  2.    remote execution of commands under GNU make.
  3.    THIS CODE IS NOT SUPPORTED BY THE GNU PROJECT.
  4.    Please do not send bug reports or questions about it to
  5.    the Make maintainers.
  6.  
  7. Copyright (C) 1988, 1989, 1992, 1993 Free Software Foundation, Inc.
  8. This file is part of GNU Make.
  9.  
  10. GNU Make is free software; you can redistribute it and/or modify
  11. it under the terms of the GNU General Public License as published by
  12. the Free Software Foundation; either version 2, or (at your option)
  13. any later version.
  14.  
  15. GNU Make is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. GNU General Public License for more details.
  19.  
  20. You should have received a copy of the GNU General Public License
  21. along with GNU Make; see the file COPYING.  If not, write to
  22. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  23.  
  24. #include "make.h"
  25. #include "commands.h"
  26. #include "job.h"
  27. #include <sys/time.h>
  28. #include <netdb.h>
  29.  
  30. #define __STRICT_BSD__        /* Don't make conflicting declarations.  */
  31. #include "customs.h"
  32.  
  33.  
  34. char *remote_description = "Customs";
  35.  
  36. /* File name of the Customs `export' client command.
  37.    A full path name can be used to avoid some path-searching overhead.  */
  38. #define    EXPORT_COMMAND    "/usr/local/bin/export"
  39.  
  40. /* ExportPermit gotten by start_remote_job_p, and used by start_remote_job.  */
  41. static ExportPermit permit;
  42.  
  43. /* Normalized path name of the current directory.  */
  44. static char *normalized_cwd;
  45.  
  46. /* Return nonzero if the next job should be done remotely.  */
  47.  
  48. int
  49. start_remote_job_p ()
  50. {
  51.   static int inited = 0;
  52.   int status;
  53.  
  54.   /* Allow the user to turn off job exportation
  55.      (useful while he is debugging Customs, for example).  */
  56.   if (getenv ("GNU_MAKE_NO_CUSTOMS") != 0)
  57.     return 0;
  58.  
  59.   if (!inited)
  60.     {
  61.       /* For secure Customs, make is installed setuid root and
  62.      Customs requires a privileged source port be used.  */
  63.       make_access ();
  64.  
  65.       /* Ping the daemon once to see if it is there.  */
  66.       inited = Customs_Ping () == RPC_SUCCESS ? 1 : -1;
  67.  
  68.       /* Return to normal user access.  */
  69.       user_access ();
  70.  
  71.       if (starting_directory == 0)
  72.     /* main couldn't figure it out.  */
  73.     inited = -1;
  74.       else
  75.     {
  76.       /* Normalize the current directory path name to something
  77.          that should work on all machines exported to.  */
  78.  
  79.       normalized_cwd = (char *) xmalloc (GET_PATH_MAX);
  80.       strcpy (normalized_cwd, starting_directory);
  81.       if (Customs_NormPath (normalized_cwd, GET_PATH_MAX) < 0)
  82.         /* Path normalization failure means using Customs
  83.            won't work, but it's not really an error.  */
  84.         inited = -1;
  85.     }
  86.     }
  87.  
  88.   if (inited < 0)
  89.     return 0;
  90.  
  91.   status = Customs_Host (EXPORT_SAME, &permit);
  92.   if (status != RPC_SUCCESS)
  93.     {
  94.       if (debug_flag)
  95.     printf ("Customs won't export: %s\n", Rpc_ErrorMessage (status));
  96.       return 0;
  97.     }
  98.  
  99.   return !CUSTOMS_FAIL (&permit.addr);
  100. }
  101.  
  102. /* Start a remote job running the command in ARGV, with environment from
  103.    ENVP.  It gets standard input from STDIN_FD.  On failure, return
  104.    nonzero.  On success, return zero, and set *USED_STDIN to nonzero if it
  105.    will actually use STDIN_FD, zero if not, set *ID_PTR to a unique
  106.    identification, and set *IS_REMOTE to nonzero if the job is remote, zero
  107.    if it is local (meaning *ID_PTR is a process ID).  */
  108.  
  109. int
  110. start_remote_job (argv, envp, stdin_fd, is_remote, id_ptr, used_stdin)
  111.      char **argv, **envp;
  112.      int stdin_fd;
  113.      int *is_remote;
  114.      int *id_ptr;
  115.      int *used_stdin;
  116. {
  117.   extern int vfork (), execve ();
  118.   char waybill[MAX_DATA_SIZE], msg[128];
  119.   struct timeval timeout;
  120.   struct sockaddr_in sin;
  121.   int len;
  122.   int retsock, retport, sock;
  123.   Rpc_Stat status;
  124.   int pid;
  125.  
  126.   /* Create the return socket.  */
  127.   retsock = Rpc_UdpCreate (True, 0);
  128.   if (retsock < 0)
  129.     {
  130.       error ("exporting: Couldn't create return socket.");
  131.       return 1;
  132.     }
  133.  
  134.   /* Get the return socket's port number.  */
  135.   len = sizeof (sin);
  136.   if (getsockname (retsock, (struct sockaddr *) &sin, &len) < 0)
  137.     {
  138.       (void) close (retsock);
  139.       perror_with_name ("exporting: ", "getsockname");
  140.       return 1;
  141.     }
  142.   retport = sin.sin_port;
  143.  
  144.   /* Create the TCP socket for talking to the remote child.  */
  145.   sock = Rpc_TcpCreate (False, 0);
  146.  
  147.   /* Create a WayBill to give to the server.  */
  148.   len = Customs_MakeWayBill (&permit, normalized_cwd, argv[0], argv,
  149.                  envp, retport, waybill);
  150.  
  151.   /* Modify the waybill as if the remote child had done `child_access ()'.  */
  152.   {
  153.     WayBill *wb = (WayBill *) waybill;
  154.     wb->euid = wb->ruid;
  155.     wb->rgid = wb->rgid;
  156.   }
  157.  
  158.   /* Send the request to the server, timing out in 20 seconds.  */
  159.   timeout.tv_usec = 0;
  160.   timeout.tv_sec = 20;
  161.   sin.sin_family = AF_INET;
  162.   sin.sin_port = htons (Customs_Port ());
  163.   sin.sin_addr = permit.addr;
  164.   status = Rpc_Call (sock, &sin, (Rpc_Proc) CUSTOMS_IMPORT,
  165.              len, (Rpc_Opaque) waybill,
  166.              sizeof(msg), (Rpc_Opaque) msg,
  167.              1, &timeout);
  168.   if (status != RPC_SUCCESS)
  169.     {
  170.       (void) close (retsock);
  171.       (void) close (sock);
  172.       error ("exporting: %s", Rpc_ErrorMessage (status));
  173.       return 1;
  174.     }
  175.   else if (msg[0] != 'O' || msg[1] != 'k' || msg[2] != '\0')
  176.     {
  177.       (void) close (retsock);
  178.       (void) close (sock);
  179.       error ("CUSTOMS_IMPORT: %s", msg);
  180.       return 1;
  181.     }
  182.   else if (debug_flag)
  183.     {
  184.       struct hostent *host = gethostbyaddr (&permit.addr, sizeof (permit.addr),
  185.                         AF_INET);
  186.       printf ("Job exported to %s ID %u\n",
  187.           host == 0 ? inet_ntoa (permit.addr) : host->h_name,
  188.           permit.id);
  189.     }
  190.  
  191.   fflush (stdout);
  192.   fflush (stderr);
  193.  
  194.   pid = vfork ();
  195.   if (pid < 0)
  196.     {
  197.       /* The fork failed!  */
  198.       perror_with_name ("vfork", "");
  199.       return 1;
  200.     }
  201.   else if (pid == 0)
  202.     {
  203.       /* Child side.  Run `export' to handle the connection.  */
  204.       static char sock_buf[20], retsock_buf[20], id_buf[20];
  205.       static char *new_argv[6] =
  206.     { EXPORT_COMMAND, "-id", sock_buf, retsock_buf, id_buf, 0 };
  207.  
  208.       /* Set up the arguments.  */
  209.       (void) sprintf (sock_buf, "%d", sock);
  210.       (void) sprintf (retsock_buf, "%d", retsock);
  211.       (void) sprintf (id_buf, "%x", permit.id);
  212.  
  213.       /* Get the right stdin.  */
  214.       if (stdin_fd != 0)
  215.     (void) dup2 (stdin_fd, 0);
  216.  
  217.       /* Unblock signals in the child.  */
  218.       unblock_sigs ();
  219.  
  220.       /* Run the command.  */
  221.       exec_command (new_argv, envp);
  222.     }
  223.  
  224.   /* Parent side.  Return the `export' process's ID.  */
  225.   (void) close (retsock);
  226.   (void) close (sock);
  227.   *is_remote = 0;
  228.   *id_ptr = pid;
  229.   return 0;
  230. }
  231.  
  232. /* Get the status of a dead remote child.  Block waiting for one to die
  233.    if BLOCK is nonzero.  Set *EXIT_CODE_PTR to the exit status, *SIGNAL_PTR
  234.    to the termination signal or zero if it exited normally, and *COREDUMP_PTR
  235.    nonzero if it dumped core.  Return the ID of the child that died,
  236.    0 if we would have to block and !BLOCK, or < 0 if there were none.  */
  237.  
  238. int
  239. remote_status (exit_code_ptr, signal_ptr, coredump_ptr, block)
  240.      int *exit_code_ptr, *signal_ptr, *coredump_ptr;
  241.      int block;
  242. {
  243.   return -1;
  244. }
  245.  
  246. /* Block asynchronous notification of remote child death.
  247.    If this notification is done by raising the child termination
  248.    signal, do not block that signal.  */
  249. void
  250. block_remote_children ()
  251. {
  252.   return;
  253. }
  254.  
  255. /* Restore asynchronous notification of remote child death.
  256.    If this is done by raising the child termination signal,
  257.    do not unblock that signal.  */
  258. void
  259. unblock_remote_children ()
  260. {
  261.   return;
  262. }
  263.  
  264. /* Send signal SIG to child ID.  Return 0 if successful, -1 if not.  */
  265. int
  266. remote_kill (id, sig)
  267.      int id;
  268.      int sig;
  269. {
  270.   return -1;
  271. }
  272.